/************************************************************
* @file   gkt_defines.h
************************************************************/

#ifndef GKT_DEFINES_H
#define GKT_DEFINES_H

#include "gkt_compiler.h"

#define GKT_INTSIZE	4
#define GKT_INTBITS	(GKT_INTSIZE << 3)

#define gkt_bit(bit)	((1U << (bit)))
#define gkt_mask(bits, shift)	((gkt_bit(bits) - 1) << (shift))

#define gkt_aligned(n, alignment)	\
	(((n) + (alignment) - 1) & (~((alignment) - 1)))

/* minimal & maximal */
#ifdef __MAX
#define gkt_max(a, b)	__MAX(a, b)
#else
#define gkt_max(a, b)	(((a) > (b)) ? (a) : (b))
#endif
#ifdef __MIN
#define gkt_min(a, b)	__MIN(a, b)
#else
#define gkt_min(a, b)	(((a) < (b)) ? (a) : (b))
#endif

/* unused macro to avoid compiler warning */
#define gkt_unused(var)	(void)(var)

/* swap endian */
#define gkt_swap_uint32(u32_value)	\
	(((uint32_t)(u32_value) << 24)	\
		| (((uint32_t)(u32_value) & 0xff00) << 8)	\
		| (((uint32_t)(u32_value) >> 8) & 0xff00)	\
		| ((uint32_t)(u32_value) >> 24))
#define gkt_swap_uint16(u16_value)	\
	((((uint16_t)(u16_value) << 8) & 0xff00) \
		| ((uint16_t)(u16_value) >> 8))

#if GKT_LITTLE_ENDIAN
#define gkt_native_to_be_u32(native_u32)	gkt_swap_uint32(native_u32)
#define gkt_native_to_le_u32(native_u32)	(native_u32)
#define gkt_native_to_be_u16(native_u16)	gkt_swap_uint16(native_u16)
#define gkt_native_to_le_u16(native_u16)	(native_u16)
#else
#define gkt_native_to_be_u32(native_u32)	(native_u32)
#define gkt_native_to_le_u32(native_u32)	gkt_swap_uint32(native_u32)
#define gkt_native_to_be_u16(native_u16)	(native_u16)
#define gkt_native_to_le_u16(native_u16)	gkt_swap_uint16(native_u16)
#endif

/* read & write 32bits register */
#define gkt_read_reg32(addr)	*((volatile uint32_t *)(addr))
#define gkt_write_reg32(addr, value)	\
	do { \
		*((volatile uint32_t *)(addr)) = (uint32_t)(value); \
	} while(0)

/* fetch - le */
#define gkt_fetch_8(addr)	*((uint8_t *)(addr))
#define gkt_fetch_le16(addr)	\
	(((uint16_t)*((uint8_t *)(addr) + 1) << 8) \
	| ((uint16_t)*((uint8_t *)(addr))))
#define gkt_fetch_le24(addr)	\
	(((uint32_t)*((uint8_t *)(addr) + 2) << 16) \
	| ((uint32_t)*((uint8_t *)(addr) + 1) << 8) \
	| ((uint32_t)*((uint8_t *)(addr))))
#define gkt_fetch_le32(addr)	\
	(((uint32_t)*((uint8_t *)(addr) + 3) << 24) \
	| ((uint32_t)*((uint8_t *)(addr) + 2) << 16) \
	| ((uint32_t)*((uint8_t *)(addr) + 1) << 8) \
	| ((uint32_t)*((uint8_t *)(addr))))
/* fetch - be */
#define gkt_fetch_be16(addr)	\
	(((uint16_t)*((uint8_t *)(addr)) << 8) \
	| ((uint16_t)*((uint8_t *)(addr) + 1)))
#define gkt_fetch_be24(addr)	\
	(((uint32_t)*((uint8_t *)(addr)) << 16) \
	| ((uint32_t)*((uint8_t *)(addr) + 1) << 8) \
	| ((uint32_t)*((uint8_t *)(addr) + 2)))
#define gkt_fetch_be32(addr)	\
	(((uint32_t)*((uint8_t *)(addr)) << 24) \
	| ((uint32_t)*((uint8_t *)(addr) + 1) << 16) \
	| ((uint32_t)*((uint8_t *)(addr) + 2) << 8) \
	| ((uint32_t)*((uint8_t *)(addr) + 3)))
/* store - le */
#define gkt_store_8(addr, data)	\
	do { *((uint8_t *)(addr)) = (uint8_t)(data); } while (0)
#define gkt_store_le16(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)(data);	\
		*((uint8_t *)(addr) + 1) = (uint8_t)((data) >> 8);	\
	} while (0)
#define gkt_store_le24(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)(data);	\
		*((uint8_t *)(addr) + 1) = (uint8_t)((data) >> 8);	\
		*((uint8_t *)(addr) + 2) = (uint8_t)((data) >> 16);	\
	} while (0)
#define gkt_store_le32(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)(data);	\
		*((uint8_t *)(addr) + 1) = (uint8_t)((data) >> 8);	\
		*((uint8_t *)(addr) + 2) = (uint8_t)((data) >> 16);	\
		*((uint8_t *)(addr) + 3) = (uint8_t)((data) >> 24);	\
	} while (0)
/* store - be */
#define gkt_store_be8(addr, data)	\
	do { *((uint8_t *)(addr)) = (uint8_t)(data); } while (0)
#define gkt_store_be16(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)((data) >> 8);	\
		*((uint8_t *)(addr) + 1) = (uint8_t)(data); \
	} while (0)
#define gkt_store_be24(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)((data) >> 16); \
		*((uint8_t *)(addr) + 1) = (uint8_t)((data) >> 8);	\
		*((uint8_t *)(addr) + 2) = (uint8_t)(data); \
	} while (0)
#define gkt_store_be32(addr, data)	\
	do {	\
		*((uint8_t *)(addr)) = (uint8_t)((data) >> 24); \
		*((uint8_t *)(addr) + 1) = (uint8_t)((data) >> 16);	\
		*((uint8_t *)(addr) + 2) = (uint8_t)((data) >> 8); \
		*((uint8_t *)(addr) + 3) = (uint8_t)(data); \
	} while (0)


/* item exist or not */
#define GKT_ITEM_EXIST_0	NONE
#define GKT_ITEM_EXIST_1	EXIST
#define GKT_ITEM_EXIST_2	EXIST
#define GKT_ITEM_EXIST_3	EXIST
#define GKT_ITEM_EXIST_4	EXIST
#define GKT_ITEM_EXIST_5	EXIST
#define GKT_ITEM_EXIST_6	EXIST
#define GKT_ITEM_EXIST_7	EXIST
#define GKT_ITEM_EXIST_8	EXIST
#define GKT_ITEM_EXIST_9	EXIST
#define GKT_ITEM_EXIST_10	EXIST
#define GKT_ITEM_EXIST_11	EXIST
#define GKT_ITEM_EXIST_12	EXIST
#define GKT_ITEM_EXIST_13	EXIST
#define GKT_ITEM_EXIST_14	EXIST
#define GKT_ITEM_EXIST_15	EXIST
#define GKT_ITEM_EXIST_16	EXIST
#define GKT_ITEM_EXIST_17	EXIST
#define GKT_ITEM_EXIST_18	EXIST
#define GKT_ITEM_EXIST_19	EXIST
#define GKT_ITEM_EXIST_20	EXIST
#define GKT_ITEM_EXIST_21	EXIST
#define GKT_ITEM_EXIST_22	EXIST
#define GKT_ITEM_EXIST_23	EXIST
#define GKT_ITEM_EXIST_24	EXIST
#define GKT_ITEM_EXIST_25	EXIST
#define GKT_ITEM_EXIST_26	EXIST
#define GKT_ITEM_EXIST_27	EXIST
#define GKT_ITEM_EXIST_29	EXIST
#define GKT_ITEM_EXIST_28	EXIST
#define GKT_ITEM_EXIST_30	EXIST
#define GKT_ITEM_EXIST_31	EXIST
#define GKT_ITEM_EXIST_32	EXIST
#define GKT_ITEM_EXIST_L1(nums)	GKT_ITEM_EXIST_##nums
#define GKT_ITEM_EXIST(nums)	GKT_ITEM_EXIST_L1(nums)


/*
 * multiple items define
 */
#define GKT_MULTI_ITEMS_DEFINE_1(ITEM_NAME)	\
	ITEM_NAME##_DEFINE(0)
#define GKT_MULTI_ITEMS_DEFINE_2(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_1(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(1)
#define GKT_MULTI_ITEMS_DEFINE_3(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_2(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(2)
#define GKT_MULTI_ITEMS_DEFINE_4(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_3(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(3)
#define GKT_MULTI_ITEMS_DEFINE_5(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_4(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(4)
#define GKT_MULTI_ITEMS_DEFINE_6(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_5(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(5)
#define GKT_MULTI_ITEMS_DEFINE_7(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_6(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(6)
#define GKT_MULTI_ITEMS_DEFINE_8(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_7(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(7)
#define GKT_MULTI_ITEMS_DEFINE_9(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_8(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(8)
#define GKT_MULTI_ITEMS_DEFINE_10(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_9(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(9)
#define GKT_MULTI_ITEMS_DEFINE_11(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_10(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(10)
#define GKT_MULTI_ITEMS_DEFINE_12(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_11(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(11)
#define GKT_MULTI_ITEMS_DEFINE_13(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_12(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(12)
#define GKT_MULTI_ITEMS_DEFINE_14(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_13(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(13)
#define GKT_MULTI_ITEMS_DEFINE_15(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_14(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(14)
#define GKT_MULTI_ITEMS_DEFINE_16(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_15(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(15)
#define GKT_MULTI_ITEMS_DEFINE_17(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_16(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(16)
#define GKT_MULTI_ITEMS_DEFINE_18(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_17(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(17)
#define GKT_MULTI_ITEMS_DEFINE_19(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_18(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(18)
#define GKT_MULTI_ITEMS_DEFINE_20(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_19(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(19)
#define GKT_MULTI_ITEMS_DEFINE_21(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_20(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(20)
#define GKT_MULTI_ITEMS_DEFINE_22(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_21(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(21)
#define GKT_MULTI_ITEMS_DEFINE_23(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_221(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(22)
#define GKT_MULTI_ITEMS_DEFINE_24(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_23(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(23)
#define GKT_MULTI_ITEMS_DEFINE_25(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_24(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(24)
#define GKT_MULTI_ITEMS_DEFINE_26(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_25(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(25)
#define GKT_MULTI_ITEMS_DEFINE_27(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_26(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(26)
#define GKT_MULTI_ITEMS_DEFINE_28(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_27(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(27)
#define GKT_MULTI_ITEMS_DEFINE_29(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_28(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(28)
#define GKT_MULTI_ITEMS_DEFINE_30(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_29(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(29)
#define GKT_MULTI_ITEMS_DEFINE_31(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_30(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(30)
#define GKT_MULTI_ITEMS_DEFINE_32(ITEM_NAME)	\
	GKT_MULTI_ITEMS_DEFINE_31(ITEM_NAME),	\
	ITEM_NAME##_DEFINE(31)

#define GKT_MULTI_ITEMS_DEFINE_L1(ITEM_NAME, ITEM_NUMS)	\
	GKT_MULTI_ITEMS_DEFINE_##ITEM_NUMS(ITEM_NAME)
#define GKT_MULTI_ITEMS_DEFINE(ITEM_NAME, ITEM_NUMS)	\
	GKT_MULTI_ITEMS_DEFINE_L1(ITEM_NAME, ITEM_NUMS)

/* NAME 2 VALUE */
#define GKT_MACRO_NAME_TO_VALUE_L1(PREFIX, NAME)	\
	PREFIX##_##NAME
#define GKT_MACRO_NAME_TO_VALUE(PREFIX, NAME)	\
	GKT_MACRO_NAME_TO_VALUE_L1(PREFIX, NAME)

#define GKT_MACRO_N2V_PN_L1(PREFIX, NAME)	\
	PREFIX##_##NAME
#define GKT_MACRO_N2V_PN(PREFIX, NAME)	\
	GKT_MACRO_N2V_PN_L1(PREFIX, NAME)

#define GKT_MACRO_N2V_PNS_L1(PREFIX, NAME, SUFFIX)	\
	PREFIX##_##NAME##_##SUFFIX
#define GKT_MACRO_N2V_PNS(PREFIX, NAME, SUFFIX)	\
	GKT_MACRO_N2V_PNS_L1(PREFIX, NAME, SUFFIX)

#endif	/* GKT_DEFINES_H */

